package com.typhoon.spring_shiro.utils.file;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Gzip文件解压缩
 * <p>
 *
 * @author weijieWang
 * @date 2015年9月17日
 */
public class GZipFileUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(GZipFileUtil.class);

    /**
     * 压缩成Gzip文件
     * <p>
     *
     * @param file
     * @return
     * @date 2015年9月17日
     * @author weijieWang
     * @throws IOException
     */
    public static boolean gZipFile(File file) throws IOException {

        if (file == null) {
            LOGGER.error("压缩文件为Null");
            return false;
        }

        BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
        BufferedOutputStream out = null;
        int endIndex = file.getAbsolutePath().lastIndexOf(".");
        String gZipFileName = file.getAbsolutePath().substring(0, endIndex) + ".gz";
        try {
            out = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(gZipFileName)));

            LOGGER.info("开始压缩文件名:" + file.getName());
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }

        } catch (IOException e) {
            LOGGER.error("压缩文件名:" + file.getName() + "失败");
            throw new IOException("压缩文件名:" + file.getName() + "失败", e);
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
        LOGGER.info("压缩文件名:" + file.getName() + "成功");
        return true;
    }

    /**
     * 解压Gzip文件
     * <p>
     *
     * @param inFileName
     * @param outFile
     * @return
     * @date 2015年9月17日
     * @author weijieWang
     * @throws IOException
     */
    public static boolean unGZipFile(String inFileName, String outFile) throws IOException {
        if (inFileName == null) {
            LOGGER.error("文件名为空");
            return false;
        }
        if (!getExtension(inFileName).equalsIgnoreCase("gz")) {
            LOGGER.error("文件必须已.gz为后缀");
            return false;
        }
        return unGZipFile(new File(inFileName), outFile);
    }

    /**
     * 解压Gzip文件
     * <p>
     *
     * @param file
     * @param outFile
     * @return
     * @date 2015年9月17日
     * @author weijieWang
     * @throws IOException
     */
    public static boolean unGZipFile(File file, String outFile) {
        if (file == null) {
            LOGGER.error("要解压的文件为null");
            return false;
        }
        LOGGER.info("开始解压文件名:" + file.getName());
        BufferedReader read = null;
        BufferedWriter print = null;
        // new PrintWriter(outFile);
        String temp = file.getName();
        try {
            read = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(file)), "UTF-8"));
            print = new BufferedWriter(new FileWriter(outFile, true));
            String pre;
            // 读取压缩文件里的内容
            pre = read.readLine();
            while (pre != null) {
                System.out.println(pre);
                print.write(pre);
                pre = read.readLine();
                if (pre != null) {
                    print.newLine();
                }
            }
        } catch (FileNotFoundException e) {
            LOGGER.error("找不到文件名:" + temp);
            return false;
        } catch (IOException e) {
            LOGGER.error("解压文件名:" + file.getName() + "失败");
            return false;
        } finally {
            try {
                if (read != null) {
                    read.close();
                }
                if (print != null) {
                    print.close();
                }
            } catch (IOException e) {
                LOGGER.error("文件流关闭异常");
            }
        }
        LOGGER.info("解压文件名:" + file.getName() + "成功");
        return true;
    }

    public static String getExtension(String f) {
        String ext = "";
        int i = f.lastIndexOf('.');

        if (i > 0 && i < f.length() - 1) {
            ext = f.substring(i + 1);
        }
        return ext;
    }

    public static String getFileName(String f, String ext) {
        String fname = f;
        int i = f.lastIndexOf('.');

        if (i > 0 && i < f.length() - 1) {
            fname = f.substring(0, i);
        }
        i = ext.indexOf('.');
        if (i < 0) {
            ext = "." + ext;
        }
        return fname + ext;
    }

    /**
     * 构建目录
     * 
     * @param outputDir
     * @param subDir
     */
    public static void createDirectory(String outputDir, String subDir) {
        File file = new File(outputDir);

        if (subDir != null && !subDir.trim().isEmpty()) {// 子目录不为空
            file = new File(outputDir + "/" + subDir);
        }

        if (!file.exists()) {
            file.mkdirs();
        }

    }

    /**
     * 将文件夹压缩
     *
     * @param resourcesPath
     * @param targetPath
     * @throws Exception
     * @date 2015年9月22日
     * @author huangtao
     */
	public static void compressedFile(String resourcesPath, String targetPath) {
	    ZipOutputStream out = null;
	    LOGGER.info("--------------将"+resourcesPath+"压缩为"+targetPath+"-------------------");
	    try{
    		File resourcesFile = new File(resourcesPath); // 源文件
    		File targetFile = new File(targetPath); // 目的
    		// 如果目的路径不存在，则新建
    		if (!targetFile.exists()) {
    			targetFile.mkdirs();
    		}
    
    		String targetName = resourcesFile.getName() + ".zip"; // 目的压缩文件名
    		FileOutputStream outputStream = new FileOutputStream(targetPath + "/" + targetName);
    		out = new ZipOutputStream(new BufferedOutputStream(outputStream));
    
    		createCompressedFile(out, resourcesFile, "");
	    }catch (Exception e){
	        LOGGER.error("压缩文件夹出现异常");
	    }finally{
	        try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                LOGGER.error("压缩文件夹出现异常");
            }
	    }
	}


	/**
	 * 递归压缩文件夹
	 *
	 * @param out
	 * @param file
	 * @param dir
	 * @throws Exception
	 * @date 2015年9月22日
	 * @author huangtao
	 */
	private static void createCompressedFile(ZipOutputStream out, File file, String dir) {
	    FileInputStream fis = null;
	    try{
    		// 如果当前的是文件夹，则进行进一步处理
    		if (file.isDirectory()) {
    			// 得到文件列表信息
    			File[] files = file.listFiles();
    			// 将文件夹添加到下一级打包目录
    			out.putNextEntry(new ZipEntry(dir + "/"));
    
    			dir = dir.length() == 0 ? "" : dir + "/";
    
    			// 循环将文件夹中的文件打包
    			for (int i = 0; i < files.length; i++) {
    				createCompressedFile(out, files[i], dir + files[i].getName()); // 递归处理
    			}
    		} else { // 当前的是文件，打包处理
    			// 文件输入流
    			fis = new FileInputStream(file);
    
    			out.putNextEntry(new ZipEntry(dir));
    			// 进行写操作
    			int j = 0;
    			byte[] buffer = new byte[1024];
    			while ((j = fis.read(buffer)) > 0) {
    				out.write(buffer, 0, j);
    			}
    		}
	    }catch (Exception e){
	        LOGGER.error("递归压缩文件夹出现异常"+e);
	    } finally{
	        // 关闭输入流
	        if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    LOGGER.error("递归压缩文件夹关闭文件输入流出现异常"+e);
                }
            }
	    }
	}
}
